/*
 * by wlh 
 * date 2025/09/17 09:56
 */
// 创建dialogue graph的底层类
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities.Editor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEditor.UIElements;
using UnityEngine;
//using UnityEngine.UI;
using UnityEngine.UIElements;
using NodeShape = MermaidParser.NodeShape;

public class DialogueGraphView : GraphView
{
    // 在构造函数里，对GraphView进行一些初始的设置
    public DialogueGraphView()
    {
        // 加载样式表
        var styleSheet = Resources.Load<StyleSheet>("NewUSSFile");
        styleSheets.Add(styleSheet);

        //Add(new GridBackground());
        // 允许对Graph进行Zoom in/out
        SetupZoom(ContentZoomer.DefaultMinScale, ContentZoomer.DefaultMaxScale);
        // 允许拖拽Content
        this.AddManipulator(new ContentDragger());
        // 允许Selection里的内容
        this.AddManipulator(new SelectionDragger());
        // GraphView允许进行框选
        this.AddManipulator(new RectangleSelector());
        /*
        // 1. 创建StartNode，并设置好其position
        var startNode = MermaidNodeFactory.CreateNode("mermaidId", NodeShape.Rect, "title", default);
        // 2. 把node加入到GraphView里
        AddElement(startNode);
        // 3. 给StartNode添加Output Port
        var portOut = GenPortForNode(startNode, Direction.Output);
        // 4. 给output改名
        portOut.portName = "out0";
        // 5. 加入到StartNode的outputContainer里
        //startNode.outputContainer.Add(port);
        startNode.inputContainer.Add(portOut);

        var portIn = GenPortForNode(startNode, Direction.Input);
        portIn.portName = "in0";
        startNode.outputContainer.Add(portIn);

        // 调用两个refresh函数
        startNode.RefreshExpandedState();
        startNode.RefreshPorts();
        */

        var node = new Node();
        node.mainContainer.Clear();

        VisualElement element1 = new ();
        //element1.style.width = 300;
        //element1.style.height = 40;
        element1.AddToClassList("blue-button");
        node.mainContainer.Add(element1);

        // 添加输入端口
        var inputPort = Port.Create<Edge>(Orientation.Vertical, Direction.Input, Port.Capacity.Multi, typeof(bool));
        inputPort.portName = "In";
        element1.style.alignItems = Align.Center;
        element1.Add(inputPort);

        VisualElement element2 = new();
        element2.AddToClassList("black-button");
        node.mainContainer.Add(element2);
        MermaidNode mermaidNode = new();
        var odinWin = OdinEditorWindow.InspectObject(mermaidNode);
        element2.Add(odinWin.rootVisualElement);

        VisualElement element3 = new();
        element3.AddToClassList("blue-button");
        node.mainContainer.Add(element3);

        var outputPort = Port.Create<Edge>(Orientation.Vertical, Direction.Output, Port.Capacity.Multi, typeof(bool));
        outputPort.portName = "Out";
        element3.style.alignItems = Align.Center;
        element3.Add(outputPort);

        var inputPort2 = Port.Create<Edge>(Orientation.Horizontal, Direction.Input, Port.Capacity.Multi, typeof(bool));
        inputPort2.portName = "In2";
        var inputPort3 = Port.Create<Edge>(Orientation.Horizontal, Direction.Input, Port.Capacity.Multi, typeof(bool));
        inputPort3.portName = "In3";
        VisualElement element4 = new();
        //element4.style.justifyContent = Justify.SpaceBetween;
        element4.Add(inputPort2);
        element4.Add(inputPort3);
        inputPort2.style.justifyContent = Justify.FlexStart;
        inputPort3.style.justifyContent = Justify.FlexEnd;
        element4.AddToClassList("blue-button");
        node.mainContainer.Add(element4);

        AddElement(node);
    }

    //可以用于连接的接口
    public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter adapter)
    {
        List<Port> compatiblePorts = new List<Port>();

        // 继承的GraphView里有个Property：ports, 代表graph里所有的port
        ports.ForEach((port) =>
        {
            // 对每一个在graph里的port，进行判断，这里有两个规则：
            // 1. port不可以与自身相连
            // 2. 同一个节点的port之间不可以相连
            if (port != startPort && port.node != startPort.node)
            {
                compatiblePorts.Add(port);
            }
        });

        // 在我理解，这个函数就是把所有除了startNode里的port都收集起来，放到了List里
        // 所以这个函数能让StartNode的Output port与任何其他的Node的Input port相连（output port应该默认不能与output port相连吧）
        return compatiblePorts;
    }

    // 添加Mermaid节点的方法
    public void AddMermaidNode(string mermaidId, NodeShape type, string title, Vector2 position = default)
    {
        var node = MermaidNodeFactory.CreateNode(mermaidId, type, title, position);
        AddElement(node);
        if (position == default)
        {
            var a = node.parent.parent.worldBound;
            var b = node.parent.parent.parent.worldBound.position;

            var rect = GUIHelper.GetCurrentLayoutRect();
            var offset = node.parent.worldBound.position;
            Vector2 v = new Vector2(251, 42);
            rect.position -= (offset - b);
            node.SetPosition(rect);
        }
    }

    private void AddOutputPort(DialogueNode node)
    {
        var outPort = GenPortForNode(node, Direction.Output, Port.Capacity.Multi);

        // 根据node的outport的数目给新的outport命名
        var count = node.outputContainer.Query("connector").ToList().Count;
        string name = $"Output {count}";
        outPort.portName = name;
        node.outputContainer.Add(outPort);
        node.RefreshExpandedState();
        node.RefreshPorts();
    }

    // 为节点n创建input port或者output port
    // Direction: 是一个简单的枚举，分为Input和Output两种
    private Port GenPortForNode(Node n, Direction portDir, Port.Capacity capacity = Port.Capacity.Multi)
    {
        // Orientation也是个简单的枚举，分为Horizontal和Vertical两种，port的数据类型是float
        return n.InstantiatePort(Orientation.Vertical, portDir, capacity, typeof(float));
    }

    //使用API将两个Node相连接
    public void ConnectEdgeByPorts(Port _outputPort, Port _inputPort)
    {
        Edge tempEdge = new Edge()
        {
            output = _outputPort,
            input = _inputPort
        };
        tempEdge.input.Connect(tempEdge);
        tempEdge.output.Connect(tempEdge);
        Add(tempEdge);
    }

    public void ConnectEdgeByNode(Node node1, Node node2)
    {
        if (node1.outputContainer.childCount < 1)
        {
            Debug.LogWarning($"{node1.title} has no output port");
            return;
        }
        if (node2.inputContainer.childCount < 1)
        {
            Debug.LogWarning($"{node2.title} has no input port");
            return;
        }
        Edge edge = new()
        {
            output = node1.outputContainer[0] as Port,
            input = node2.inputContainer[0] as Port,
        };
        edge.input.Connect(edge);
        edge.output.Connect(edge);
        //Edge.edgeControl.inputArrow
        edge.edgeControl.drawToCap = true; // invalid
        edge.edgeControl.drawFromCap = true;  // invalid
        //Add(tempEdge);
        AddElement(edge);
    }

    public void AddGroup()
    {
        // 创建Comment Block
        var group = new Group
        {
            autoUpdateGeometry = true,
            title = "Comment Block<br> 111<br> 222"
        };
        AddElement(group);
        group.SetPosition(new Rect(500, 20, 200, 100));
    }

    // 添加一个方法来触发布局
    public void OrganizeLayout()
    {
        // 使用层级布局
        GraphLayout.OrganizeNodesLeftToRight(this);

        // 或者使用简单网格布局
        // MermaidLayoutOrganizer.SimpleGridLayout(this, 3); // 3列
    }

    // 在您的 GraphView 管理器类中
    public string ExportToMermaid()
    {
        string mermaidCode = GraphToMermaid.ConvertToMermaid(this, "测试图");
        Debug.Log("生成的 Mermaid 代码:");
        Debug.Log(mermaidCode);

        // 复制到剪贴板，方便粘贴到 Mermaid 编辑器中测试
        GUIUtility.systemCopyBuffer = mermaidCode;
        Debug.Log("Mermaid 代码已复制到剪贴板");

        // 保存到文件
        //GraphToMermaid.SaveToFile(this, Application.dataPath + "/MyGraph.mmd", "测试图");
        return mermaidCode;
    }

    public void LoadPositionsFromMermaid(string mermaidContent)
    {
        GraphToMermaid.ApplyPositionsFromMermaid(this, mermaidContent);
    }

    void Test()
    {
        // 获取Node的InputPort和OutputPort
        //Port outP = nodes.AtIndex(0).outputContainer[0].Q<Port>();
        //Port inP = rootPlayableNode.inputContainer[0].Q<Port>();

    }
}

// 创建dialogue graph的底层节点类
public class DialogueNode : Node
{
    public string GUID;
    public string Text;
    public bool Entry = false;
}


public static class MermaidNodeFactory
{
    // 定义节点类型与格式的映射字典
    private static readonly Dictionary<NodeShape, string> NodeFormatMap = new()
    {
        { NodeShape.Rect, "[{0}]" },
        { NodeShape.Circle, "(({0}))" },
        { NodeShape.RoundRect, "({0})" },
        { NodeShape.Rhombus, "{{{0}}}" },
        { NodeShape.Stadium, "([{0}])" },
        { NodeShape.Subroutine, "[[{0}]]" },
        { NodeShape.Cylinder, "[({0})]" },
        { NodeShape.Hexagon, "{{{{{0}}}}}" }, // 注意: 这里是四个大括号，因为需要转义
        { NodeShape.ParallelogramRight, "[/{0}/]" },
        { NodeShape.ParallelogramLeft, "[\\{0}\\]" },
        { NodeShape.DoubleCircle, "((({0})))" },
        { NodeShape.Asymmetric, ">{0}]" },
        { NodeShape.Trapezoid, "[/{0}\\]" },
        { NodeShape.InvertedTrapezoid, "[\\{0}/]" },
        { NodeShape.CircleRect, "({0})" } // 与 RoundRect 语法相同
    };

    public static void SetNode(string guid, string mermaidId, string text, NodeShape shape, bool entry)
    {
        var node = DialogueGraphWindow.graphView.nodes.First(n => n.viewDataKey == guid);

        var mermaidNode = node.userData as MermaidNode;
        mermaidNode.mermaidId = mermaidId;
        mermaidNode.Text = text;
        mermaidNode.shape = shape;
        mermaidNode.Entry = entry;
        //mermaidNode.GUID = guid;// 不变

        node.title = GetTitleWithIcon(shape, mermaidId, text);
        node.userData = mermaidNode;

        // 应用样式
        ApplyStyle(node, shape, false);

        // 刷新节点
        node.RefreshExpandedState();
        node.RefreshPorts();
    }

    // 创建Mermaid节点
    public static Node CreateNode(string mermaidId, NodeShape shape, string text, Vector2 position)
    {
        MermaidNode mermaidNode = new()
        {
            GUID = Guid.NewGuid().ToString(),
            mermaidId = mermaidId,
            Text = text,
            shape = shape,
            Entry = false
        };
        Node node = new()
        {
            title = GetTitleWithIcon(shape, mermaidId, text),
            viewDataKey = mermaidNode.GUID, //mermaidId, //Guid.NewGuid().ToString()
            userData = mermaidNode,
        };

        Button btn = new(() => 
        {
            //var btnRect = GUIHelper.GetCurrentLayoutRect();
            var btnRect = node.GetPosition();
            btnRect = node.parent.LocalToWorld(btnRect);            
            OdinEditorWindow.InspectObjectInDropDown(mermaidNode.Clone(), btnRect, btnRect.width);

        }) 
        { text = "Set Node" };

        btn.AddToClassList("red-button");

        //node.titleContainer.Add(btn);
        node.titleButtonContainer.Add(btn);
        //node.extensionContainer.Add(textField);

        // 设置位置
        node.SetPosition(new Rect(position, Vector2.zero));

        // 添加输入端口
        var inputPort = Port.Create<Edge>(Orientation.Vertical, Direction.Input, Port.Capacity.Multi, typeof(bool));
        inputPort.portName = "In";
        node.inputContainer.Add(inputPort);
        //node.titleContainer.Insert(0, inputPort);

        // 添加输出端口
        var outputPort = Port.Create<Edge>(Orientation.Vertical, Direction.Output, Port.Capacity.Multi, typeof(bool));
        outputPort.portName = "Out";
        node.outputContainer.Add(outputPort);
        //node.topContainer.Insert(1, outputPort);
        // 应用样式
        ApplyStyle(node, shape);
        
        // 刷新节点
        node.RefreshExpandedState();
        node.RefreshPorts();

        return node;
    }

    // 获取带图标的标题
    private static string GetTitleWithIcon(NodeShape type, string id, string title)
    {
        title = $"{id}|{title}";
        return type switch
        {
            NodeShape.Rect => "■ 矩形(默认常规步骤或操作)<br>" + title,
            NodeShape.Circle => "● 圆形(开始或结束1)<br>" + title,
            NodeShape.RoundRect => "▢ 圆角矩形(开始或结束2)<br>" + title,
            NodeShape.Rhombus => "◆ 菱形(判断或分支)<br>" + title,
            NodeShape.Subroutine => "▣ (子流程)<br>" + title,
            // 下面的形状都不能正确显示
            NodeShape.Stadium => "⬬ 跑道形(特定流程，如数据库操作或预处理)<br>" + title,
            NodeShape.Cylinder => "⬡ 圆柱形(数据库或数据存储)<br>" + title,
            _ => "■ 不支持(默认矩形)<br>" + title
        };
    }

    // 应用样式
    private static void ApplyStyle(Node node, NodeShape type, bool addBg = true)
    {
        // 移除可能存在的旧样式类
        foreach (NodeShape value in Enum.GetValues(typeof(NodeShape)))
        {
            node.RemoveFromClassList(value.ToString().ToLower());
        }

        // 添加对应的样式类
        node.AddToClassList(type.ToString().ToLower());

        // 设置节点颜色
        Color color = GetColorForType(type);
        node.titleContainer.style.backgroundColor = new StyleColor(color);

        // 使用固定的深色文字，确保在任何背景下都可见
        node.titleContainer.style.color = new StyleColor(new Color(0.1f, 0.1f, 0.1f));

        if (!addBg)
            return;

        // 添加半透明背景增强文字可读性
        var textBackground = new VisualElement();
        textBackground.style.backgroundColor = new StyleColor(new Color(0, 0, 0, 0.7f));
        textBackground.style.position = Position.Absolute;
        textBackground.style.left = 6;
        textBackground.style.right = 0;
        textBackground.style.top = 0;
        textBackground.style.height = 38;
        node.titleContainer.Add(textBackground);
        textBackground.SendToBack();
    }

    // 根据类型获取颜色
    private static Color GetColorForType(NodeShape type)
    {
        return type switch
        {
            NodeShape.Rect => new Color(0.2f, 0.4f, 0.8f), // 蓝色
            NodeShape.Circle => new Color(0.4f, 0.8f, 0.2f), // 绿色
            NodeShape.RoundRect => new Color(0.8f, 0.6f, 0.2f), // 橙色
            NodeShape.Rhombus => new Color(0.8f, 0.2f, 0.4f), // 红色
            NodeShape.Stadium => new Color(0.6f, 0.2f, 0.8f), // 紫色
            NodeShape.Subroutine => new Color(0.2f, 0.8f, 0.6f), // 青绿色
            NodeShape.Cylinder => new Color(0.8f, 0.8f, 0.2f), // 黄色
            _ => new Color(0.5f, 0.5f, 0.5f) // 默认灰色
        };
    }
}